﻿
namespace Patterns4Net.PatternEnforcer.Core.Patterns
{
    using System.Linq;
    using Mono.Cecil;
    using Mono.Cecil.Rocks;
    using Patterns4Net.Core.Patterns;

    [PatternCheckerExport(typeof(Strategy))]
    public sealed class StrategyChecker : FluentPatternChecker<Strategy>
    {
        public StrategyChecker()
        {
            this.If(t => t.TargetType.IsInterface)
                .Type(p => p.TargetType)
                .Check(t => t.Methods.Count == 1, t => string.Format(ErrorMessages.StrategyShouldHaveMethod, t.Name));

            this.If(t => t.TargetType.IsInterface == false)
                .Type(p => p.TargetType)
                .Check(t => t.GetMethods().Count() == 1, t => string.Format(ErrorMessages.StrategyShouldHaveMethod, t.Name))
                .Check(HasVirtualMethod, HasNotVirtualMethodError);
        }

        private static bool HasVirtualMethod(TypeDefinition type)
        {
            var method = type.Methods.FirstOrDefault();
            return method != null && (method.IsAbstract || method.IsVirtual);            
        }

        private static string HasNotVirtualMethodError(TypeDefinition type)
        {
            var method = type.Methods.Select(m => m.Name).FirstOrDefault();
            return string.Format(ErrorMessages.StrategyMethodShouldBeOverrideable, method, type.Name);
        }
    }
}
